﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Xml.Serialization;

namespace WowTourGuideTranslator
{
    /// <summary>
    /// base class for all wowhead parser classes
    /// </summary>
    [Serializable]
    public abstract class WowheadBaseParser
    {
        #region declarations

        /// <summary>
        /// Helper class for all translated wowhead data
        /// </summary>
        [Serializable]
        public class TranslatedWowheadData
        {
            /// <summary>
            /// Initializes a new instance of the <see cref="TranslatedWowheadData"/> class.
            /// </summary>
            public TranslatedWowheadData()
            {
                this.Name = new TranslatedPair();
            }

            /// <summary>
            /// Gets or sets the type.
            /// </summary>
            /// <value>The type.</value>
            public string Type { get; set; }

            /// <summary>
            /// Gets or sets the id.
            /// </summary>
            /// <value>The id.</value>
            public int Id { get; set; }

            /// <summary>
            /// Gets or sets the name.
            /// </summary>
            /// <value>The name.</value>
            public TranslatedPair Name { get; set; }

        }

        #endregion

        #region fields

        const string wowHeadUrlFormat = @"http://{0}.wowhead.com/?{1}={2}";

        const string nameRegex = @"^<h1>(?<name>[^<]+)";

        protected string originalPage;
        
        protected string transPage;

        protected readonly string language;

        #endregion fields

        #region constructor

        /// <summary>
        /// Initializes a new instance of the <see cref="WowheadBaseParser"/> class.
        /// </summary>
        public WowheadBaseParser()
        {
            this.language = DataProvider.DataLanguage;
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="WowHeadBaseParser"/> class.
        /// </summary>
        /// <param name="type">The type.</param>
        /// <param name="id">The id.</param>
        /// <param name="language">The language.</param>
        public WowheadBaseParser(string type, int id, string language)
        {
            this.language = language;

            System.Net.WebClient wwwClient = new System.Net.WebClient();

            try
            {
                // dowload english page
                originalPage = Encoding.UTF8.GetString(wwwClient.DownloadData(this.GetUrlForData(Language.English, type, id)));
            }
            catch (Exception ex)
            {
                throw new TourGuideDownloadException(this.GetUrlForData(Language.English, type, id), ex);
            }

            try
            {
                //download translated page
                transPage = Encoding.UTF8.GetString(wwwClient.DownloadData(this.GetUrlForData(language, type, id)));
            }
            catch (Exception ex)
            {
                throw new TourGuideDownloadException(this.GetUrlForData(language, type, id), ex);
            }

            this.ParsePages();
        }

        #endregion constructor

        #region methods
        /// <summary>
        /// Gets the URL for data.
        /// </summary>
        /// <param name="language">The language.</param>
        /// <param name="requestType">Type of the request.</param>
        /// <param name="id">The id.</param>
        /// <returns></returns>
        protected string GetUrlForData(string language, string requestType, int id)
        {
            return string.Format(wowHeadUrlFormat, language, requestType, id);
        }

        /// <summary>
        /// Parses the pages.
        /// </summary>
        protected virtual void ParsePages()
        {
            Match baseMatch = Regex.Match(this.originalPage, nameRegex, RegexOptions.IgnoreCase | RegexOptions.Multiline);
            Match transMatch = Regex.Match(this.transPage, nameRegex, RegexOptions.IgnoreCase | RegexOptions.Multiline);

            if (baseMatch.Success && transMatch.Success)
            {
                this.Name = new TranslatedPair()
                {
                    Language = this.language,
                    Original = baseMatch.Groups[@"name"].Value,
                    Translated = transMatch.Groups[@"name"].Value
                };

                // add translation 
                if (!DataProvider.TranslationsDict.ContainsKey(this.Name.Original))
                    DataProvider.TranslationsDict.Add(this.Name.Original, this.Name.Translated);
            }
        }

        #endregion methods

        #region properies

        /// <summary>
        /// Gets or sets the name.
        /// </summary>
        /// <value>The name.</value>
        [XmlElement]
        public TranslatedPair Name { get;  set; }

        #endregion properies


    }
}
